/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

/***********************************************************************
 *
 * FILENAME:
 * systemInfo.c
 *
 * PURPOSE:
 *   Collects system info
 *
 * CREATED:
 * 11/2000 by Cory Dixon
 *
 * LAST MODIFIED:
 * $Author: dixonc $
 * $Date: 2005/11/02 20:27:20 $
 * $Revision: 1.8 $
 *
 ***********************************************************************/

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/dir.h>
#include <sys/statfs.h>

#include "systemInfo.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

int getStat(struct statinfo *stats)
{

	int fd=-1;
	char *p=NULL;
	char buf[STAT_BUF_LEN];

	if( stats == NULL ) {
		perror("-- getStat() -- no stat pointer");
		return -1;
	}

	fd = open("/proc/stat", O_RDONLY);
	if (fd < 0) {
		perror("-- getStat() -- open");
		return -1;
	}

	if (read(fd, buf, STAT_BUF_LEN-1) < 1) {
		perror("-- getStat() -- read");
		return -2;
	}
	buf[STAT_BUF_LEN-1] = '\0';
	close(fd);

	p = strstr(buf, "cpu ");
	if (p)
		sscanf(p, "cpu  %lu %lu %lu %lu %lu", &(stats->cpu_user),
				&(stats->cpu_nice), &(stats->cpu_system),
				&(stats->cpu_idle), &(stats->cpu_iowait));

	//printf("CPU:  %lu %lu %lu %lu %lu\n", (stats->cpu_user),
	//(stats->cpu_nice), (stats->cpu_system),
	//(stats->cpu_idle), (stats->cpu_iowait));

	return 1;
}

float calcCPU(struct statinfo *now, struct statinfo *last)
{
	if( !now || !last) {
		perror("-- calcCPU() -- no pointers");
		return -1;
	}

	unsigned long user = now->cpu_user - last->cpu_user;
	unsigned long nice = now->cpu_nice - last->cpu_nice;
	unsigned long system = now->cpu_system - last->cpu_system;
	unsigned long idle = now->cpu_idle - last->cpu_idle;
	unsigned long iowait = now->cpu_iowait - last->cpu_iowait;

	double total = user+nice+system+idle+iowait;
	double used = user+nice+system+iowait;

	//printf("Usage %%:  %f %f %f %f %f => %f\n", user/total, nice/total, system/total,
	//idle/total, iowait/total, used/total*100);

	return (float)(used / total * 100.0);

}

float calcMem(struct meminfo *memPtr)
{
	if( !memPtr) {
		perror("-- calcMem() -- no pointer");
		return -1;
	}

	return (float)(100.0 * (memPtr->mem_total - memPtr->mem_free)/(float)memPtr->mem_total);   
}

float calcSwap(struct meminfo *memPtr)
{
	if( !memPtr) {
		perror("-- calcSwap() -- no pointer");
		return -1;
	}
	return (float)(100.0 * (memPtr->swap_total - memPtr->swap_free)/(float)memPtr->swap_total);   
}

int getMem(struct meminfo *memPtr)
{

	int fd=0;
	char *p=NULL;
	char buf[STAT_BUF_LEN];

	if( !memPtr) {
		perror("-- getMem() -- no pointer");
		return -1;
	}

	fd = open("/proc/meminfo", O_RDONLY);
	if (fd < 0) {
		perror("-- getMem() -- open");
		return -1;
	}

	if (read(fd, buf, STAT_BUF_LEN-1) < 1) {
		perror("-- getMem() -- read");
		return -2;
	}
	buf[STAT_BUF_LEN-1] = '\0';
	close(fd);

	p = strstr(buf, "MemTotal: ");
	if (p) sscanf(p, "MemTotal:  %lu", &(memPtr->mem_total));
	else return 0;

	p = strstr(buf, "MemFree: ");
	if (p) sscanf(p, "MemFree:  %lu", &(memPtr->mem_free));
	else return 0;

	unsigned long cached;
	p = strstr(buf, "Cached: ");
	if (p) sscanf(p, "Cached:  %lu", &(cached));
	else return 0;
	//printf("cached=%lu  mem_free=%lu\n",cached,memPtr->mem_free+cached);
	// don't count cached files as used memory for user
	memPtr->mem_free = memPtr->mem_free+cached;

	p = strstr(buf, "SwapTotal: ");
	if (p) sscanf(p, "SwapTotal:  %lu", &(memPtr->swap_total));
	else return 0;

	p = strstr(buf, "SwapFree: ");
	if (p) sscanf(p, "SwapFree:  %lu", &(memPtr->swap_free));
	else return 0;

	memPtr->mem_total  *= 1024;
	memPtr->mem_free   *= 1024;
	memPtr->swap_total *= 1024;
	memPtr->swap_free  *= 1024;

	return 1;
}

int getDisk (struct statfs *disk)
{

	if( !disk) {
		perror("-- getDisk() -- no pointer");
		return -1;
	}

	if( statfs( "/", disk) != 0 ) {
		perror("-- getDisk() -- statfs error for '/' ");
		return -1;
	}  

	return 1;

	// calculate the available user space
	//  disk.f_bavail * (float) disk.f_bsize;
}

#ifdef __cplusplus
}
#endif /* __cplusplus */

